#include "acceptor.h"
#include "echo_connection.h"
#include "event_loop.h"
#include "event_loop_thread_pool.h"
#include "thread_pool.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/epoll.h>

namespace {
int createListenSocket(uint16_t port) {
    int fd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (fd == -1) throw std::runtime_error("socket failed");

    int opt = 1;
    ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);

    if (::bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
        throw std::runtime_error("bind failed");
    }
    if (::listen(fd, SOMAXCONN) == -1) {
        throw std::runtime_error("listen failed");
    }
    return fd;
}
}

int main() {
    EventLoop mainLoop;                                     // 主 Reactor：只处理 accept
    EventLoopThreadPool ioPool(mainLoop, 4);                // 4 个 I/O 线程
    ioPool.start();

    ThreadPool computePool(std::thread::hardware_concurrency());  // 业务计算线程池

    int listenFd = createListenSocket(8080);
    Acceptor acceptor(mainLoop, listenFd);

    // 当有新连接时，轮询选择一个 sub-loop 并在其线程内注册 EchoConnection
    acceptor.setNewConnectionCallback([&](int connFd) {
        EventLoop& ioLoop = ioPool.getNextLoop();
        ioLoop.runInLoop([connFd, &ioLoop, &computePool]() {
            auto* conn = new EchoConnection(ioLoop, connFd, computePool);
            ioLoop.addHandler(connFd, EPOLLIN | EPOLLET, conn);
        });
    });

    mainLoop.addHandler(listenFd, EPOLLIN | EPOLLET, &acceptor);
    mainLoop.loop();  // 阻塞运行主 Reactor

    return 0;
}